package com.ginmeta.common.exception;

import cn.dev33.satoken.exception.*;
import cn.hutool.core.util.ObjectUtil;
import com.ginmeta.common.base.AjaxResult;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.resource.NoResourceFoundException;

import java.util.List;

/**
 * 全局异常处理
 * @author GinMeta
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 未找到静态资源
     */
    @ExceptionHandler(NoResourceFoundException.class)
    public AjaxResult handleNoResourceFoundException(NoResourceFoundException e,
                                                     HttpServletRequest request) {
        String requestUri = request.getRequestURI();
        log.error("请求地址：{}，{}", requestUri, e.getMessage());
        return AjaxResult.error(e.getMessage());
    }

    /**
     * 请求方式不支持
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public AjaxResult handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e,
                                                          HttpServletRequest request) {
        String requestUri = request.getRequestURI();
        log.error("请求地址'{}',不支持'{}'请求", requestUri, e.getMethod());
        return AjaxResult.error(e.getMessage());
    }

    /**
     * 自定义异常
     */
    @ExceptionHandler(CustomException.class)
    public AjaxResult handleServiceException(CustomException e) {
        log.error(e.getMessage(), e);
        Integer code = e.getCode();
        return ObjectUtil.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(e.getMessage());
    }

    /**
     * 自定义验证异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        List<FieldError> errors = e.getBindingResult().getFieldErrors();
        StringBuilder sb = new StringBuilder();
        for (FieldError error : errors) {
            if (sb.length() <= 0) {
                sb.append(error.getDefaultMessage());
            } else {
                sb.append("、").append(error.getDefaultMessage());
            }
        }
        return AjaxResult.error(sb.toString(), null);
    }

    /**
     * 拦截未知的运行时异常
     */
    @ExceptionHandler(RuntimeException.class)
    public AjaxResult handleRuntimeException(RuntimeException e, HttpServletRequest request) {
        String requestUri = request.getRequestURI();
        log.error("请求地址'{}',发生未知异常.", requestUri, e);
        return AjaxResult.error(e.getMessage());
    }

    /**
     * 拦截：未登录异常
     * @param e 异常
     * @param request 请求
     * @return 结果
     */
    @ExceptionHandler(NotLoginException.class)
    public AjaxResult handlerException(NotLoginException e, HttpServletRequest request) {
        log.error("请求地址：{}，{}", request.getRequestURI(), e.getMessage());
        // 返回给前端
        return AjaxResult.error(50001, e.getMessage());
    }

    /**
     * 拦截：缺少权限异常
     * @param e 异常
     * @return 结果
     */
    @ExceptionHandler(NotPermissionException.class)
    public AjaxResult handlerException(NotPermissionException e, HttpServletRequest request) {
        log.error("请求地址：{}，{}", request.getRequestURI(), e.getMessage());
        return AjaxResult.error(50003,"您账号目前没有该权限");
    }

    /**
     * 拦截：缺少角色异常
     * @param e 异常
     * @param request 请求
     * @return 结果
     */
    @ExceptionHandler(NotRoleException.class)
    public AjaxResult handlerException(NotRoleException e, HttpServletRequest request) {
        log.error("请求地址：{}，{}", request.getRequestURI(), e.getMessage());
        return AjaxResult.error(50002,"您账号目前角色没有该权限");
    }

    /**
     * 拦截：服务封禁异常
     * @param e 异常
     * @param request 请求
     * @return 结果
     */
    @ExceptionHandler(DisableServiceException.class)
    public AjaxResult handlerException(DisableServiceException e, HttpServletRequest request) {
        log.error("请求地址'{}',服务封禁异常，{}", request.getRequestURI(), e.getMessage());
        log.error("当前账号 " + e.getService() + " 服务已被封禁 (level=" + e.getLevel() + ")：" + e.getDisableTime() + "秒后解封");
        return AjaxResult.error("当前账号 " + e.getService() + " 服务已被封禁 (level=" + e.getLevel() + ")：" + e.getDisableTime() + "秒后解封");
    }

    /**
     * 拦截：Http Basic 校验失败异常
     * @param e 异常
     * @param request 请求
     * @return 结果
     */
    @ExceptionHandler(NotHttpBasicAuthException.class)
    public AjaxResult handlerException(NotHttpBasicAuthException e, HttpServletRequest request) {
        log.error("请求地址'{}',Http Basic 校验失败异常，{}", request.getRequestURI(), e.getMessage());
        return AjaxResult.error(e.getMessage());
    }


    /**
     * 拦截：其它所有异常
     * @param e 异常
     * @return 结果
     */
    @ExceptionHandler(Exception.class)
    public AjaxResult handlerException(Exception e, HttpServletRequest request) {
        String requestUri = request.getRequestURI();
        log.error("请求地址'{}',发生系统异常.", requestUri, e);
        return AjaxResult.error(e.getMessage());
    }

}
